import re, uiautomation as auto
import sys

TITLE_PATTERNS = [r'.*BOSS直聘.*']            # 标题模糊匹配
CHROME_CLASSES = {'Chrome_WidgetWin_0', 'Chrome_WidgetWin_1'}
MAX_DEPTH = 100
SEARCH_TMO = 3.0
PER_ITEM_TMO = 3.0

def list_top_windows():
    root = auto.GetRootControl()
    rows = []
    for w in root.GetChildren():
        try:
            rows.append((w.ControlTypeName, w.Name or '', w.ClassName or '', w))
        except Exception:
            pass
    for i, (t, n, c, _) in enumerate(rows, 1):
        print(f"{i:02d}. type={t:14} name='{n}' class='{c}'",file=sys.stderr)
    return rows

def name_matches(name: str) -> bool:
    return any(re.fullmatch(pat, name or '') for pat in TITLE_PATTERNS)


def get_boss_window(timeout: float = 3.0):
    """
    获取 BOSS直聘 根控件（WindowControl 或 PaneControl）
    :param timeout: 查找超时，秒
    :return: Control 对象或 None
    """
    with auto.UIAutomationInitializerInThread():
        auto.SetGlobalSearchTimeout(0.5)

        # 1) 先尝试 WindowControl（标准顶层窗口）
        win = auto.WindowControl(RegexName=r'.*BOSS直聘.*', searchDepth=1)
        if win.Exists(timeout, 0.2):
            return win

        # 2) 回退：在顶层 PaneControl 里找（Electron/Chromium 应用常见）
        root = auto.GetRootControl()
        for c in root.GetChildren():
            if 'BOSS直聘' in (c.Name or '') and c.ClassName in ('Chrome_WidgetWin_0', 'Chrome_WidgetWin_1'):
                return c

    print("❌ 未找到 BOSS直聘 窗口",file=sys.stderr)

    return None


def pick_boss_root():
    """返回最合理的 BOSS 根节点（Window 或 Pane）"""
    # 1) 先尝试 WindowControl（如果 BOSS 是真正的顶层窗口）
    for pat in TITLE_PATTERNS:
        win = auto.WindowControl(RegexName=pat, searchDepth=1)
        if win.Exists(SEARCH_TMO, 0.2):
            return win

    # 2) 回退：在顶层子控件中找 PaneControl + Class=Chrome_WidgetWin_* + Name 匹配
    tops = list_top_windows()  # 也顺便打印出来方便你核对
    candidates = []
    for _, name, cls, elem in tops:
        if cls in CHROME_CLASSES and name_matches(name):
            candidates.append(elem)

    if candidates:
        # 取面积最大者作为根
        def area(e):
            try:
                r = e.BoundingRectangle
                return max(0, (r.right - r.left)) * max(0, (r.bottom - r.top))
            except Exception:
                return -1
        return max(candidates, key=area)

    return None


def get_all_texts(root_ctrl, max_depth=None):
    """
    遍历 root_ctrl 下的所有子孙，收集 Text/Document 控件的 Name
    """
    texts = []

    def walk(ctrl, depth=0):
        if max_depth is not None and depth > max_depth:
            return
        try:
            children = ctrl.GetChildren()
        except Exception:
            return
        for c in children:
            try:
                if c.ControlTypeName in ('TextControl', 'GroupControl'):
                    if c.Name:  # 去掉空
                        texts.append(c.Name.strip())
            except Exception:
                pass
            walk(c, depth+1)

    walk(root_ctrl)
    return texts


# def is_visible(ctrl):
#     try:
#         # 基础可见性检查
#         if ctrl.IsOffscreen:
#             return False
#         r = ctrl.BoundingRectangle
#         if r.right <= r.left or r.bottom <= r.top:
#             return False
#
#         # 检查控件是否在屏幕范围内
#         from ctypes import windll
#         sw = windll.user32.GetSystemMetrics(0)  # 屏幕宽度
#         sh = windll.user32.GetSystemMetrics(1)  # 屏幕高度
#         if r.right <= 0 or r.bottom <= 0 or r.left >= sw or r.top >= sh:
#             return False
#
#         # 额外检查：控件是否具有有效的可见性状态（部分应用可能通过此属性控制显示）
#         if hasattr(ctrl, 'IsVisible') and not ctrl.IsVisible:
#             return False
#
#         return True
#     except Exception:
#         return False


def is_visible(ctrl):
    """
    修复版：消息列表可见性判断（放宽严格条件，确保正常消息项能被识别）
    核心逻辑：只保留“绝对不可见”的判断，避免误杀正常消息
    :param ctrl: 消息项控件（ListItemControl/GroupControl）
    :return: bool - 控件是否可见
    """
    try:
        # 1. 核心隐藏状态检查（Electron应用最可靠的隐藏标记）
        if hasattr(ctrl, 'IsOffscreen') and ctrl.IsOffscreen:
            return False
        if hasattr(ctrl, 'IsVisible') and not ctrl.IsVisible:
            return False

        # 2. 坐标有效性检查（只排除完全无效的控件，放宽尺寸限制）
        r = ctrl.BoundingRectangle
        width = r.right - r.left
        height = r.bottom - r.top
        # 仅排除尺寸为0的空白控件（取消最小宽高限制，适配不同分辨率下的消息项）
        if width <= 50 or height <= 50:
            return False

        # 3. 屏幕边界检查（大幅放宽容错，仅排除完全超出屏幕的项）
        from ctypes import windll
        screen_width = windll.user32.GetSystemMetrics(0)
        screen_height = windll.user32.GetSystemMetrics(1)
        # 仅当控件完全在屏幕外时才排除（避免窗口最大化/缩放导致的误判）
        if r.right <= 50 or r.bottom <= 50 or r.left >= screen_width or r.top >= screen_height:
            return False

        # 4. 简化父级检查（仅追溯1级父控件，避免因父容器属性异常导致误判）
        parent = ctrl.GetParentControl() if ctrl else None
        if parent and hasattr(parent, 'IsOffscreen') and parent.IsOffscreen:
            return False

        # 5. 移除容易误判的条件（删除透明度、IsEnabled、关键词过滤）
        # （这些条件在BOSS直聘中并非消息项可见性的必要判断依据）

        return True
    except Exception as e:
        # 异常时默认返回True（避免因个别控件异常导致所有消息项被过滤）
        print(f"⚠️  可见性判断异常: {str(e)}", file=sys.stderr)
        return True

'''
消息数量: []
消息信息: ['08月12日', '李美丽', '品类运营', '[我已读]', '你好，请问还招聘吗？']
坐标 (553, 1829)


消息数量: ['1']
消息信息: ['08月12日', '姜迎迎', '品类运营', '[未读]', '您好，上班时间是怎样的？']
坐标 (553, 1965)


消息数量: ['2']
消息信息: ['08月11日', '顾路臣', '品类运营', '[未读]', '吗']
坐标 (553, 2102)
'''



def fully_visible(rect, view_rect, pad=20):
    """rect 是否完全可见于 view_rect（四周留 pad 安全边距）"""
    item = rect.BoundingRectangle
    div = view_rect.BoundingRectangle
    return (
        item.top + pad    >= div.top  and
        item.bottom - pad <= div.bottom
        # item.left   >= div.left + pad and
        # item.right  <= div.right - pad
    )



def get_message_list(win):
    with auto.UIAutomationInitializerInThread():
        if win == None:
            win = get_boss_window()
        #win = get_boss_window()  # pick_boss_root()
        win.Exists(3, 0.2)  # 超时等待
        allBtn = auto.TextControl(searchFromControl=win, Name='全部')
        parent = allBtn.GetParentControl().GetParentControl()

        big_div = allBtn.GetParentControl().GetNextSiblingControl().GetNextSiblingControl().GetNextSiblingControl()


        parent = parent.GetChildren()[3]

        children = parent.GetFirstChildControl().GetChildren()
        result = []
        # child 天蓝色标记
        for child in children:
            if is_visible(child) == False:
                continue
            if child.GetFirstChildControl().ControlTypeName == 'ListItemControl':
                # 没有置顶的数据
                for GetChild in child.GetChildren():
                    # if is_visible(GetChild) == False:

                    if GetChild.ControlTypeName == 'ListItemControl':

                        if fully_visible(GetChild, big_div) == False:
                            continue

                        # print(get_all_texts(child,10))
                        firstChild = GetChild.GetFirstChildControl().GetFirstChildControl()
                        unreadMessageList = get_all_texts(firstChild.GetFirstChildControl(), 10)
                        # print('消息数量:', unreadMessageList,file=sys.stderr)
                        messageList = get_all_texts(firstChild.GetLastChildControl(), 10)

                        if len(unreadMessageList) > 0:
                            last = messageList.pop()
                            messageList.append('[未读]')
                            messageList.append(last)

                        if len(messageList) == 4:
                            last = messageList.pop()
                            messageList.append('[我已读]')
                            messageList.append(last)

                        result.append(
                            {
                                'time': messageList[0],
                                'name': messageList[1],
                                'post': messageList[2],
                                'state': messageList[3],
                                'content': messageList[4],
                                'position': firstChild.GetPosition(),
                            }
                        )

            if len(child.GetChildren()) == 1 and child.GetFirstChildControl().ControlTypeName == 'GroupControl':
                #置顶数据
                unreadMessageList = get_all_texts(child.GetFirstChildControl().GetFirstChildControl(), 10)
                # print('消息数量:', unreadMessageList,file=sys.stderr)
                messageList = get_all_texts(child, 10)

                if len(unreadMessageList) > 0:
                    messageList.pop(0)
                    last = messageList.pop()
                    messageList.append('[未读]')
                    messageList.append(last)

                if len(messageList) == 4:
                    last = messageList.pop()
                    messageList.append('[我已读]')
                    messageList.append(last)

                result.append(
                    {
                        'time': messageList[0],
                        'name': messageList[1],
                        'post': messageList[2],
                        'state': messageList[3],
                        'content': messageList[4],
                        'position': child.GetPosition(),
                    }
                )


        return result

# print('开始执行')
# results = get_message_list(None)
# print(results)